package cn.zzdt4j.config.service.biz.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.zzdt4j.common.constant.ConfigModifyTypeConstants;
import cn.zzdt4j.common.extension.enums.DelEnum;
import cn.zzdt4j.common.toolkit.BeanUtil;
import cn.zzdt4j.common.toolkit.UserContext;
import cn.zzdt4j.config.mapper.ConfigInfoMapper;
import cn.zzdt4j.config.model.ConfigAllInfo;
import cn.zzdt4j.config.model.ConfigInfoBase;
import cn.zzdt4j.config.model.LogRecordInfo;
import cn.zzdt4j.config.model.biz.threadpool.*;
import cn.zzdt4j.config.service.biz.ConfigService;
import cn.zzdt4j.config.service.biz.OperationLogService;
import cn.zzdt4j.config.service.biz.ThreadPoolService;
import cn.zzdt4j.config.verify.ConfigModificationVerifyServiceChoose;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * The type Thread pool service.
 *
 * @author by <a href="mailto:ligang941012@gmail.com">gang.Li</a>
 * @since 2023 /11/7 21:54
 */
@Service
@AllArgsConstructor
public class ThreadPoolServiceImpl implements ThreadPoolService {

    private final ConfigInfoMapper configInfoMapper;

    private final ConfigService configService;

    private final OperationLogService operationLogService;

    private final ConfigModificationVerifyServiceChoose configModificationVerifyServiceChoose;

    private static final List<String> AUDITABLE_ROLES = CollectionUtil.toList("ROLE_ADMIN", "ROLE_MANAGE");

    @Override
    public void deletePool(ThreadPoolDelReqDTO reqDTO) {
        configInfoMapper.delete(
                Wrappers.lambdaUpdate(ConfigAllInfo.class)
                        .eq(ConfigAllInfo::getTenantId, reqDTO.getTenantId())
                        .eq(ConfigAllInfo::getItemId, reqDTO.getItemId())
                        .eq(ConfigAllInfo::getTpId, reqDTO.getTpId()));
        recordOperationLog(reqDTO);
    }

    private void recordOperationLog(ThreadPoolDelReqDTO requestParam) {
        LogRecordInfo logRecordInfo = LogRecordInfo.builder()
                .bizKey(requestParam.getItemId() + "_" + requestParam.getTpId())
                .bizNo(requestParam.getItemId() + "_" + requestParam.getTpId())
                .operator(UserContext.getUserName())
                .action("删除线程池: " + requestParam.getTpId())
                .category("THREAD_POOL_DELETE")
                .detail(JSONUtil.toJsonStr(requestParam))
                .createTime(new Date())
                .build();
        operationLogService.record(logRecordInfo);
    }

    @Override
    public void saveOrUpdateThreadPoolConfig(String identify, ThreadPoolSaveOrUpdateReqDTO reqDTO) {
        // check login permissions
        if (AUDITABLE_ROLES.contains(UserContext.getUserRole())) {
            final ConfigAllInfo configAllInfo = BeanUtil.convert(reqDTO, ConfigAllInfo.class);
            final Long executeTimeOut = Objects.equals(configAllInfo.getExecuteTimeOut(), 0L) ? null : configAllInfo.getExecuteTimeOut();
            configAllInfo.setExecuteTimeOut(executeTimeOut);
            configService.insertOrUpdate(identify, false, configAllInfo);
        } else {
            final ConfigModifySaveReqDTO modifySaveReqDTO = BeanUtil.convert(reqDTO, ConfigModifySaveReqDTO.class);
            modifySaveReqDTO.setCorePoolSize(reqDTO.getCoreSize());
            modifySaveReqDTO.setMaximumPoolSize(reqDTO.getMaxSize());
            modifySaveReqDTO.setModifyUser(UserContext.getUserName());
            modifySaveReqDTO.setModifyAll(false);
            modifySaveReqDTO.setType(ConfigModifyTypeConstants.THREAD_POOL_MANAGER);
            configModificationVerifyServiceChoose.choose(modifySaveReqDTO.getType()).saveConfigModifyApplication(modifySaveReqDTO);
        }
    }

    @Override
    public void alarmEnable(String id, Integer isAlarm) {
        final ConfigAllInfo configAllInfo = configInfoMapper.selectById(id);
        Assert.notNull(configAllInfo, "Current threadPool is not exist!");
        configAllInfo.setIsAlarm(isAlarm);
        configService.insertOrUpdate(null, false, configAllInfo);
    }

    @Override
    @SuppressWarnings("unchecked")
    public IPage<ThreadPoolRespDTO> queryThreadPoolPage(ThreadPoolQueryReqDTO reqDTO) {
        final LambdaQueryWrapper<ConfigAllInfo> wrapper = Wrappers.lambdaQuery(ConfigAllInfo.class)
                .eq(StrUtil.isNotBlank(reqDTO.getTenantId()), ConfigInfoBase::getTenantId, reqDTO.getTenantId())
                .eq(StrUtil.isNotBlank(reqDTO.getItemId()), ConfigInfoBase::getItemId, reqDTO.getItemId())
                .eq(StrUtil.isNotBlank(reqDTO.getTpId()), ConfigInfoBase::getTpId, reqDTO.getTpId())
                .eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL.getIntCode())
                .orderByDesc(reqDTO.getDesc() != null, ConfigAllInfo::getGmtCreate);
        return configInfoMapper.selectPage(reqDTO, wrapper).convert(each -> BeanUtil.convert(each, ThreadPoolRespDTO.class));
    }

    @Override
    public ThreadPoolRespDTO getThreadPool(ThreadPoolQueryReqDTO reqDTO) {
        final ConfigAllInfo configAllInfo = configService.findConfigAllInfo(reqDTO.getTpId(), reqDTO.getItemId(), reqDTO.getTenantId());
        return BeanUtil.convert(configAllInfo, ThreadPoolRespDTO.class);
    }

    @Override
    public List<ThreadPoolRespDTO> getThreadPoolByItemId(String itemId) {
        final LambdaQueryWrapper<ConfigAllInfo> queryWrapper = Wrappers.lambdaQuery(ConfigAllInfo.class)
                .eq(ConfigInfoBase::getItemId, itemId);
        final List<ConfigAllInfo> configAllInfos = configInfoMapper.selectList(queryWrapper);
        return BeanUtil.convert(configAllInfos, ThreadPoolRespDTO.class);
    }
}
